/// <reference path="../vswd-ext_2.0.1.js" />

Ext.namespace('FileManager'); 

////////////////////////////////////////////////////////////////////
//
//                  FileManager.GridBase
//
/////////////////////////////////////////////////////////////////// 
FileManager.GridBase = function(config) {
    this.events = {
        "containerclick" : true,
        "containerdblclick" : true,
        "containercontextmenu" : true,
        "continermousedown" : true,
        "itemdblclick": true,
        "itemcontextmenu": true,
        "selectionchange": true,
        "beforeitemdrop": true,
        "itemdrop":true
    };        
    
    FileManager.GridBase.superclass.constructor.call(this, Ext.applyIf(config || {}, {
        
        plugins: [
            new FileManager.FilesGrid.DragSelector({dragSafe:true})
        ],        
          
        view: new FileManager.FilesGridView({
            forceFit:true,
            tpl: config.tpl,
            emptyText: config.emptyText || ''
        })     
    }));    
    
    this.on('rowcontextmenu', this.onRowContextMenu, this);
    this.on('rowdblclick', this.onRowDblClick, this);
    this.getSelectionModel().on('selectionchange', this.onSelectionChange, this);
        
};

Ext.extend(FileManager.GridBase, Ext.grid.GridPanel, {

   initEvents : function(){
        FileManager.GridBase.superclass.initEvents.call(this);
	    var myDrop = new Ext.dd.DropTarget(this.body, { 
		    
		    grid: this,
            dropAllowed: 'x-dd-drop-ok', 
            dropNotAllowed: 'x-dd-drop-nodrop',
	        ddGroup: this.ddGroup || 'defaultDD', 
	        dropAllowedTarget: this.dropAllowedTarget,
	        dropNotAllowedTarget: this.dropNotAllowedTarget,
	        
	        notifyDrop: function(dd, e, data) 
	        { 
	            // first we check if this is a valid drop point
	            var dnTarget = e.getTarget(this.dropNotAllowedTarget);
	            if(dnTarget) {
	                return false;
	            }
	            // if user drops on a row we get index of that row and use it in drop event
	            var rowIndex = this.grid.getView().findRowIndex(e.getTarget(this.dropAllowedTarget));
	            // now lets build drop event
                var dropEvent = {
                    grid : this.grid,
                    rowIndex: rowIndex,
                    data: data,
                    source: dd,
                    rawEvent: e
                };	               
	            if(false === this.grid.fireEvent("beforeitemdrop", dropEvent)) {
	                return false;
	            }
		        this.grid.fireEvent("itemdrop", dropEvent);
		        return true;
	        },
		   
	        notifyOver: function(dd, e, data) 
	        { 
	            //check if the row is allowed, return true or false 
	            var daTarget = e.getTarget(this.dropAllowedTarget);
	            var dnTarget = e.getTarget(this.dropNotAllowedTarget);
	            if(dnTarget) {
	                return this.dropNotAllowed;
	            } else {
	                return this.dropAllowed;
	            }		            
	        }
	    });	        
    },

    onRowContextMenu: function(grd, index, e) {
        if(this.getSelectionModel().isSelected(index) !== true) {
            this.getSelectionModel().clearSelections();
            this.getSelectionModel().selectRow(index);
        }
        this.fireEvent("itemcontextmenu", this, e);
    },
    
    onRowDblClick: function(grd, index, e) {
        this.fireEvent("itemdblclick", grd, index, e);
    },
    
    onSelectionChange: function(sm) {
        this.fireEvent("selectionchange", this, sm.getSelections());
    },
    
    setTemplate: function(tpl) {
        this.getView().tpl = tpl;
        this.getView().refresh(false);
        return;
    },
    
    selectAll: function() {
        this.getSelectionModel().selectAll();
    },         
    
    // private
    processEvent : function(name, e){
        this.fireEvent(name, e);
        var t = e.getTarget();
        var v = this.view;
        var header = v.findHeaderIndex(t);
        var row = v.findRowIndex(t);
        if(header !== false){
            this.fireEvent("header" + name, this, header, e);
        }else if(row !== false){
            var cell = v.findCellIndex(t);
            if(row !== false){
                this.fireEvent("row" + name, this, row, e);
                if(cell !== false){
                    this.fireEvent("cell" + name, this, row, cell, e);
                }
            }
        }else if(e.target == this.getView().mainBody.dom) {
            if( this.fireEvent("container" + name, this, e) !== false)
                this.getSelectionModel().clearSelections();
        }
    }

});




////////////////////////////////////////////////////////////////////
//
//                  FileManager.FoldersTree
//
/////////////////////////////////////////////////////////////////// 
FileManager.FoldersTree = function() {

    this.events = {
        "foldersload" : true,
        "folderclick" : true,
        "foldermove": true,
        "folderdrop": true           
    };
    
    FileManager.FoldersTree.superclass.constructor.call(this, {
        animate:true, 
        loader: new Ext.tree.TreeLoader({
        	dataUrl:'../file/tree.jsp',
        	baseParams : {
        		'sessionId' : MyDesktop.currentSessionId
        	}
        }),
        enableDD:true,
        containerScroll: true,
        ddGroup: 'defaultDD',
        rootVisible:false,
        ddAppendOnly: true,
        autoScroll:true,
        border: false,
        title: Plugin.messages["FileManager.FoldersTree.title"],
        header: false,
        lines: false,
        cls: 'db-folders-tree'
    });

    // set the root node
    var root = new Ext.tree.AsyncTreeNode({
        text: 'Root',
        allowDrag:false,
        allowDrop:false,
        children: []
    });
    this.setRootNode(root);               
    root.expand();   
    
    this.on('click', this.tree_click, this);
    this.on('beforemovenode', this.tree_beforemovenode, this);
    this.on('beforenodedrop', this.tree_beforenodedrop, this);    
};

Ext.extend(FileManager.FoldersTree, Ext.tree.TreePanel, {

    tree_click: function(node, e) {
        this.fireEvent("folderclick", node.id);
    },
    
    tree_beforemovenode : function(tree, node, oldParent, newParent, index) {
        newParent.expand();
        this.fireEvent('foldermove', this.getNodeFolder(node), this.getNodeFolder(newParent));
        return false;
    },
    
    tree_beforenodedrop: function(dropEvent) {
        this.fireEvent('folderdrop', this.getNodeFolder(dropEvent.target), dropEvent);
    },    
    
    getNodeFolder: function(node) {
        return {'ID': node.id,
                'Name': node.text,
                'Type': node.attributes['type']
                }
    },
    
    getFolderById: function(folderId) {
        var node = this.getNodeById(folderId);
        if (node)
            return this.getNodeFolder(node);
        else
            return null;
    },
    
    selectFolderById: function(folderId) {
        var node = this.getNodeById(folderId);
        node.parentNode.expand();
        node.select();
    },

    getSelectedFolder: function() {
        var node = this.getSelectionModel().getSelectedNode()
        return this.getNodeFolder(node);
    }, 
    
    getRecycleBin: function() {
        var node = this.root.lastChild;
        var folder = this.getNodeFolder(node);
        if(folder.Type == FileManager.FolderType.RecycleBin)
            return folder;
        else
            return null;
    },  
    
    getMyFoldersRoot: function() {
        var node = this.root.firstChild;
        return this.getNodeFolder(node);        
    }, 
    
    selectRoot: function() {
        this.root.firstChild.select();
    },
    
    getParentFolder: function(folderId) {
        var node = this.getNodeById(folderId);
        if(node && node.parentNode && node.parentNode != this.root)
            return this.getNodeFolder(node.parentNode);
        else
            return null;
    },
    
    clearSelections: function() {
        this.getSelectionModel().clearSelections();
    },

    loadComplete: function(childs) {
        this.root.attributes.children = childs;
        this.root.reload();    
        this.loaded = true;
        
        // fire load event
        this.fireEvent("foldersload", this);
    },
        
    loadTree: function(compact) {
		
        var instance = this;        
        var conn = new Ext.data.Connection();
        Ext.Ajax.request({
            url: '../file/tree.jsp',
            method: 'post',
            params: {
            	'compact' : (compact ? true : false),
            	'sessionId' : MyDesktop.currentSessionId        		
            },
            callback: function(options, success, response) {
                var result = Ext.util.JSON4Java.decode(response.responseText);
                if (success) {
                    instance.loadComplete(result);
                } else {
                    var msg = (result && result.Message) ? result.Message : 'Some error happend. Please try again';
                    Ext.MessageBox.alert('Error', msg);                               
                }
            }             
        });        
    }
        
});



////////////////////////////////////////////////////////////////////
//
//                  FileManager.FilesGrid
//
/////////////////////////////////////////////////////////////////// 
FileManager.FilesGrid = function(currentView) {
    this.events = {
        "loadcomplete" : true
    };
    
    this.sortField = "size";
    this.sortDirection = "asc";
    
    this.templates = {};
    
	this.templates.thumbnailsView = new Ext.Template('<div class="db-fg-thumbView {cls}">' +
		                '<div class="db-icn db-ft-{icon}-medium">{thumbnail}</div>' +
		                '<div class="db-txt db-ellipsis"><span ext:qtip="{name}" unselectable="on">{name}</span></div></div>');
		                
	this.templates.iconsView = new Ext.Template('<div class="db-fg-iconView {cls}">' +
		                '<div class="db-icn db-ft-{icon}-medium">&#160;</div>' +
		                '<div class="db-txt db-ellipsis"><span ext:qtip="{name}" unselectable="on">{name}</span></div></div>');    
		                
	this.templates.tilesView = new Ext.Template('<div class="db-fg-tileView {cls}">' +
		                '<div class="db-icn db-ft-{icon}-large">&#160;</div>' +
		                '<div class="db-txt db-ellipsis"><span class="nm" unselectable="on">{name}</span><span class="tp" unselectable="on">{type}</span><span class="sz" unselectable="on">{sizeString}</span></div></div>'); 		                
    
    // create the Data Store
    this.store = new Ext.data.SimpleStore({
        id: 0,
        fields:[{name:'name',mapping:'name',sortType:'asUCString'},
                {name:'id',mapping:'id'},
                {name:'folder',mapping:'folder'},
                {name:'size',mapping:'size'},
                {name:'type',mapping:'type'},
                {name:'path',mapping:'path'},
                {name:'icon',mapping:'icon'},
                {name:'dateCreated',mapping:'dateCreated',type:'date',dateFormat:'Y/m/d H:i'},
                {name:'dateModified',mapping:'dateModified',type:'date',dateFormat:'Y/m/d H:i'},
                {name:'folderType',mapping:'folderType'},
                {name:'description',mapping:'description'},
                {name:'tags',mapping:'tags'},
                {name:'status',mapping:'status'}],
        data: []
    });    
    this.store.setDefaultSort(this.sortField, this.sortDirection);  
    
    function formatSize(val, p, r) {
        return (r.data.folder) ? '' : Ext.util.Format.fileSize(val);
    }
    
    function formatName(val, p, r) {
        return '<div class="db-fg-detailView ' + (r.data.folder ? 'db-fg-folder' : 'db-fg-file') + '">' +
                   '<div class="db-icn db-ft-'+r.data.icon+'-small">&#160;</div>' +
                   '<div class="db-txt db-ellipsis" unselectable="on">' + val + '</span></div>' + 
               '</div>';
    }
    
    function getThumbnail(data) {
        var regExp = /\.jpg$|\.jpeg$|\.gif$|\.png$|\.bmp$/i;
        if(regExp.test(data.name)) {
            return '<table cellpadding="0" cellspacing="0"><tr><td><img src="../file/public/download?FileID=' + data.id + '&thumbnail=true&sessionId=' + MyDesktop.currentSessionId + '" /></td></tr></table>';
        } else {
            return '&#160;';
        }
    };    
    
    this.columns = [
        {id: 'clName', header: Plugin.messages["FileManager.FilesGrid.column.name"], sortable: true, renderer: formatName, dataIndex: "name" },     
        {header: Plugin.messages["FileManager.FilesGrid.column.path"], width:200, sortable: true, locked: false, dataIndex: "path",hidden:true},
        {header: Plugin.messages["FileManager.FilesGrid.column.size"], width:40, align: 'right', sortable: true, renderer: formatSize, dataIndex: "size"},
        {header: Plugin.messages["FileManager.FilesGrid.column.type"], width:60, sortable: true, locked: false, dataIndex: "type"},
        {header: Plugin.messages["FileManager.FilesGrid.column.modified"], width:50, sortable: true, renderer: Ext.util.Format.dateRenderer('m/d/Y H:i'), dataIndex: "dateModified"}
    ];      
    
    FileManager.FilesGrid.superclass.constructor.call(this, {
        enableDragDrop: true,
        ddGroup: 'defaultDD',
        dropAllowedTarget: '.db-fg-folder',
        dropNotAllowedTarget: '.db-fg-file',
        border: false,       
        tpl: this.getTemplate(currentView),
        emptyText: '<div style="text-align:center;color:#000">'+Plugin.messages["FileManager.FilesGrid.folderEmpty"]+'</div>'   
    });         
    
    this.getView().prepareData = function(data) {
        data.thumbnail = getThumbnail(data);
        data.shortName = Ext.util.Format.ellipsis(data.name, 15);
        data.sizeString = data.folder ? '' : Ext.util.Format.fileSize(data.size);
        data.cls = (data.folder) ? 'db-fg-folder' : 'db-fg-file';      
        return data;
    };            
};

Ext.extend(FileManager.FilesGrid, FileManager.GridBase, {
    
    getTemplate: function(cv) {
        switch(cv) {
            case 'thumbs':
                return this.templates.thumbnailsView;
                
            case 'tiles':
                return this.templates.tilesView;                   
                
            case 'icons':
                return this.templates.iconsView;
            
            case 'details':
                return null;
        }
    },
    
    setupView: function(view) {
        this.setTemplate(this.getTemplate(view));
    },    

    getSelectedFolders: function() {
        return this.getFoldersFromRecords(this.getSelectionModel().getSelections());
    },
    
    getAllFolders: function() {    
        return this.getFoldersFromRecords(this.getStore().getRange());           
    },     
    
    getFoldersFromRecords: function(records) {
        var folders = [];
        var record = null;
        var data = null;
        var index = 0;
        while(record = records[index]) {
            data = record.data;
            if (data && data.folder) {
                folders[folders.length] = {
                    'ID': data.id,
                    'Name': data.name,
                    'CreateDate': data.dateCreated,
                    'Type': data.folderType,
                    'Description': data.description,
                    'Tags':data.tags || '',
                    'Path':data.path || this.currentPath,
                    'Status':data.status || 0
                };
            }
            index++;
        }
        return folders;
    }, 
    
    getAllFiles: function() {
        return this.getFilesFromRecords(this.getStore().getRange());    
    },    
    
    getSelectedFiles: function() {
        return this.getFilesFromRecords(this.getSelectionModel().getSelections());       
    },     
    
    getFilesFromRecords: function(records) {
        var files = [];
        var record = null;
        var data = null;
        var index = 0;
        while(record = records[index]) {
            data = record.data;
            if (data && !data.folder) {
                files[files.length] = {
                    'ID': data.id,
                    'Name': data.name,
                    'Size': data.size,
                    'CreateDate': data.dateCreated,
                    'LastModified': data.dateModified, 
                    'Type': data.folderType,
                    'Description': data.description,
                    'Tags':data.tags || '',
                    'Path':data.path || this.currentPath,
                    'Status':data.status || 0
                };
            }
            index++;
        }
        return files;    
    },  
    
    sort: function() {
        this.getStore().sort(this.sortField, this.sortDirection); 
    },
    
    setSortDirection: function(dir) {
        this.sortDirection = dir || this.sortDirection;
        this.sort();
    },
    
    setSortField: function(fieldName) {
        this.sortField = fieldName || this.sortField;
        this.sort();
    },           
    
    // private
    getDragDropText : function(){
        var count = this.selModel.getCount();
        return count == 1 ? this.selModel.getSelected().data.name : count + Plugin.messages["FileManager.FilesGrid.dragDropText"];
    },    
    
    loadComplete: function(result) {
        
        this.currentFolderId = result.currentFolderID;
        this.parentFolderId = result.parentFolderID;
        this.currentFolderType = result.currentFolderType;
        this.currentPath = result.currentPath;
        //this.items = result.Rows;
        // load data into view
        this.getStore().loadData(result.rows);  
       
        // fire load event
        this.fireEvent("loadcomplete", this);
    },
        
    loadView: function(folderId, save) {
    
        var instance = this;        
        var conn = new Ext.data.Connection();
        Ext.Ajax.request({
            url: '../file/view.jsp',
            method: 'post',
            params: {
            	'folder' : (folderId ? folderId : ''), 
            	'save' : (save != null) ? save : true ,
            	'sessionId' : MyDesktop.currentSessionId
            },
            callback: function(options, success, response) {
                var result = Ext.util.JSON.decode(response.responseText);
                if (success) {
                    instance.loadComplete(result);
                } else {
                    var msg = (result && result.Message) ? result.Message : 'Some error happend. Please try again';
                    Ext.MessageBox.alert('Error', msg);                            
                }
            }             
        });
    }    

});


////////////////////////////////////////////////////////////////////
//
//                  FileManager.FilesGridView
//
////////////////////////////////////////////////////////////////////
FileManager.FilesGridView = Ext.extend(Ext.grid.GridView, {
    
    tpl: null,
    
    initTemplates : function(){                      
        
        FileManager.FilesGridView.superclass.initTemplates.call(this);
                    
        if(!this.templatedNode){
            this.templatedNode = new Ext.XTemplate(
                    '<div class="db-fg-item x-grid3-row x-unselectable">{content}</div>'
            );
        }
        this.templatedNode.compile();                          
    },
    
    prepareData : function(data){
        return data;
    },
    
    doRender : function(cs, rs, ds, startRow, colCount, stripe){
    
        if(this.tpl === null) {
            return FileManager.FilesGridView.superclass.doRender.apply(this, arguments);
        }
        
        // buffers
        var buf = [], rp = {}, r;
        for(var j = 0, len = rs.length; j < len; j++){
            r = rs[j];
            r.data = this.prepareData(r.data);
            rp.content = this.tpl.apply(r.data);
            buf[buf.length] =  this.templatedNode.apply(rp);
        }
        return buf.join("") + '<div style="clear:both"></div>';
    },
    
    updateAllColumnWidths : function(){
        
        if(this.tpl === null) {
            return FileManager.FilesGridView.superclass.updateAllColumnWidths.apply(this);
        }    
    
        var tw = this.getTotalWidth();
        var clen = this.cm.getColumnCount();
        var ws = [];
        for(var i = 0; i < clen; i++){
            ws[i] = this.getColumnWidth(i);
        }

        this.innerHd.firstChild.firstChild.style.width = tw;

        for(var i = 0; i < clen; i++){
            var hd = this.getHeaderCell(i);
            hd.style.width = ws[i];
        }

        this.onAllColumnWidthsUpdated(ws, tw);
    },
    
    // private
    updateColumnWidth : function(col, width){
    
        if(this.tpl === null) {
            return FileManager.FilesGridView.superclass.updateColumnWidth.apply(this, arguments);
        }    
    
        var w = this.getColumnWidth(col);
        var tw = this.getTotalWidth();

        this.innerHd.firstChild.firstChild.style.width = tw;
        var hd = this.getHeaderCell(col);
        hd.style.width = w;

        this.onColumnWidthUpdated(col, w, tw);
    },    
    
    updateColumnHidden : function(col, hidden){
    
        if(this.tpl === null) {
            return FileManager.FilesGridView.superclass.updateColumnHidden.apply(this, arguments);
        }        
    
        var tw = this.getTotalWidth();

        this.innerHd.firstChild.firstChild.style.width = tw;

        var display = hidden ? 'none' : '';

        var hd = this.getHeaderCell(col);
        hd.style.display = display;
        
        this.onColumnHiddenUpdated(col, hidden, tw);

        delete this.lastViewWidth; // force recalc
        this.layout();
    }
});



////////////////////////////////////////////////////////////////////
//
//                  FileManager.FilesGrid.DragSelector
//
/////////////////////////////////////////////////////////////////// 
FileManager.FilesGrid.DragSelector = function(cfg){
    cfg = cfg || {};
    var grid, view, mb, regions, proxy, tracker;
    var rs, bodyRegion, dragRegion = new Ext.lib.Region(0,0,0,0);
    var dragSafe = cfg.dragSafe === true;

    this.init = function(grd){
        grid = grd;
        view = grd.getView();
        grid.on('render', onRender);
    };

    function fillRegions(){
        rs = [];
        var gr = view.getRows();
        for(var j = 0; j < gr.length; j++) {
            rs[rs.length] = Ext.get(gr[j]).getRegion();
        }
        bodyRegion = mb.getRegion();
    }

    function cancelClick(){
        return false;
    }

    function onBeforeStart(e){
        var r = new Ext.lib.Region(mb.getTop(), mb.getLeft() + mb.getViewSize().width, mb.getTop() + mb.getViewSize().height, mb.getLeft());
        var b = (e.getTarget('.x-grid3-scroller') == mb.dom) && r.contains(e.getPoint());
        return b;        
    }

    function onStart(e){
        grid.on('containerclick', cancelClick, view, {single:true});         
        proxy = mb.first('.x-view-selector');
        if(!proxy){
            proxy = mb.createChild({cls:'x-view-selector'});
        }
        fillRegions();

        grid.getSelectionModel().clearSelections();
    }

    function onDrag(e){
        var startXY = tracker.startXY;
        var xy = tracker.getXY();

        var x = Math.min(startXY[0], xy[0]);
        var y = Math.min(startXY[1], xy[1]);
        var w = Math.abs(startXY[0] - xy[0]);
        var h = Math.abs(startXY[1] - xy[1]);

        dragRegion.left = x;
        dragRegion.top = y;
        dragRegion.right = x+w;
        dragRegion.bottom = y+h;

        dragRegion.constrainTo(bodyRegion);
        proxy.setRegion(dragRegion);

        for(var i = 0, len = rs.length; i < len; i++){
            var r = rs[i], sel = dragRegion.intersect(r);
            if(sel && !r.selected){
                r.selected = true;
                grid.getSelectionModel().selectRow(i, true);
            }else if(!sel && r.selected){
                r.selected = false;
                grid.getSelectionModel().deselectRow(i);
            }
        }
    }

    function onEnd(e){
        if(proxy) {
            proxy.remove();
        }
    }

    function onRender(grd){
        tracker = new Ext.dd.DragTracker({
            onBeforeStart: onBeforeStart,
            onStart: onStart,
            onDrag: onDrag,
            onEnd: onEnd
        });
        mb = Ext.get(grd.getView().mainBody.findParent('.x-grid3-scroller'));       
        tracker.initEl(mb);
    }
};



////////////////////////////////////////////////////////////////////
//
//                  FileManager.SharingDialog
//
/////////////////////////////////////////////////////////////////// 
FileManager.SharingDialog = function(config) {
    config.resizable = false;
    config.constrainHeader = true;
    config.width = 345;
    config.height = 440;
    
    config.buttons = [
        {text : Plugin.messages["FileManager.common.ok"], handler: this.save, scope: this},
        {text : Plugin.messages["FileManager.common.cancel"], handler: this.close, scope: this}
    ];
    
    FileManager.SharingDialog.superclass.constructor.call(this, config);
       
    helpElm = this.body.createChild({
        tag: 'div',
        cls: 'hlp',
        style: 'padding:5px',
        html: Plugin.messages["FileManager.SharingDialog.help"]
    });
    
    var formElm = this.body.createChild({
        tag: 'div',
        cls: 'x-moz-cur-fx',
        style: 'padding:5px;',
        html: '<div style="padding:5px"><input type="checkbox" /> '+Plugin.messages["FileManager.SharingDialog.check.title"]+'</div>'
    });
    
    // Create the form
    sharingForm = new Ext.form.FormPanel({
        labelWidth: 50,
        labelAlign: 'right',
        border: false,
        disabled: true,
        maskDisabled: false,
        bodyStyle: 'background-color:Transparent',
        items: [{
            xtype:'fieldset',
            title: Plugin.messages["FileManager.SharingDialog.fieldset.title"],
            
            autoHeight:true,
            html: '<table cellspacing="3">' +
                  '<tr><td>'+Plugin.messages["FileManager.SharingDialog.userName"]+':</td><td><input type="text" style="width:230px;margin-bottom:2px;" id="x-sharing-dialog-user" /></td></tr>' +
                  '<tr><td>'+Plugin.messages["FileManager.SharingDialog.permission"]+':</td><td><input type="radio" name="rbPermission" id="x-sharing-dialog-permission" /> '+Plugin.messages["FileManager.SharingDialog.fullControl"]+' &nbsp;<input type="radio" name="rbPermission" checked="true" /> '+Plugin.messages["FileManager.SharingDialog.view"]+'</td></tr>' +
                  '<tr><td colspan="2" id="x-sharing-dialog-btnAdd"></td></tr>' +
                  '<tr><td colspan="2"><div id="x-sharing-dialog-grid" style="height:130px;overflow:auto;background-color:#fff;border:solid 1px #7F9DB9;"></div></td></tr>' +
                  '<tr><td colspan="2" align="right" id="x-sharing-dialog-btnRemove"></td></tr>' +
                  '<tr><td>'+Plugin.messages["FileManager.SharingDialog.comment"]+':</td><td><input type="text" id="x-sharing-dialog-comment" /></td></tr>' +
                  '</table>'
        }]        
    });
        
    sharingForm.render(formElm.dom);
    
    var btnAdd = new Ext.Button({renderTo:'x-sharing-dialog-btnAdd', text:Plugin.messages["FileManager.SharingDialog.button.add"]});
    btnAdd.on('click', this.btnAdd_Click, this);
    var btnRemove = new Ext.Button({renderTo:'x-sharing-dialog-btnRemove', text:Plugin.messages["FileManager.SharingDialog.button.remove"]});
    btnRemove.on('click', this.btnRemove_Click, this);
    
    // add address book field
    var add_field = new Ext.form.AddressBookField({
        width: 230,
        hideMailAddress: true,
        getSubUserName: true,
        applyTo: 'x-sharing-dialog-user'
    });   
    
    var cmt_field = new Ext.form.TextField({
        width: 230,
        applyTo: 'x-sharing-dialog-comment'
    }); 
    
    // create the grid
    permissionsArray = new Array();
    gridDataStore = new Ext.data.Store({
            proxy: new Ext.data.MemoryProxy(permissionsArray),
            reader: new Ext.data.ArrayReader({id: 0}, [
                   {name: 'username'},
                   {name: 'permission'},
                   {name: 'notify', type: 'bool'}
              ])
    });    
    var notifyRenderer = function(notify) {
        if(notify)
            return '<img src="../file/images/icons/email.gif" alt="send notification email to this user" style="float:left;padding-left:5px" />';
        else
            return "";
    };
    var colModel = new Ext.grid.ColumnModel([
        {id: "clName", header: Plugin.messages["FileManager.SharingDialog.grid.user"], sortable: true, locked: false, dataIndex: "username"},     
        {header: Plugin.messages["FileManager.SharingDialog.grid.permission"], sortable: true, locked: false, dataIndex: "permission"},
        {header: Plugin.messages["FileManager.SharingDialog.grid.notify"], sortable: true, locked: false, dataIndex: "notify", width: 40, renderer: notifyRenderer}
    ]);   
    permissionsGrid = new Ext.grid.GridPanel({
        ds: gridDataStore,
        cm: colModel,
        applyTo: 'x-sharing-dialog-grid',
        autoExpandColumn: 'clName',
        monitorWindowResize: true,        
        enableColLock: false,	
        enableColumnMove: false,
        enableHdMenu: false,
        border: false,
        width: 290,
        selModel: new Ext.grid.RowSelectionModel()
    });   
    permissionsGrid.render();    
    permissionsGrid.on('celldblclick', this.cellDoubleClicked, this);
    permissionsGrid.on('cellclick', this.cellClicked, this);
    
    chkShareFolder = Ext.get(formElm.dom.childNodes[0].childNodes[0]);
    chkShareFolder.on('click', this.toggleSharing , this);
    
    txtComment = Ext.get('x-sharing-dialog-comment').dom;
    shareItem = null;
    
    this.events = {"save" : true};       
    
    this.initSharingDialog();  
};

Ext.extend(FileManager.SharingDialog, Ext.Window, {
    initSharingDialog: function() {
        var sharingInformationLoaded = function(result,success,error) {
            shareItem = result;
            for(var i=0;i<shareItem.permissions.length;i++) {
            	if(shareItem.permissions[i]._javaClass) {
            		delete shareItem.permissions[i]._javaClass;
            	}
            }
            this.addNotify();
            this.bindSharingDialog();
            this.show();
        };
        
        RemoteMethods.GetSharedItem(this.folderId, sharingInformationLoaded, this);
    },
    
    bindSharingDialog: function() {
        
        chkShareFolder.dom.checked = shareItem.enabled;
        this.toggleSharing();
        
        txtComment.value = (txtComment.value != '') ? txtComment.value : (shareItem.comment || '');
    
        permissionsArray.length = 0;        
        var itemIndex = 0;
        var prm = null;
        while (prm = shareItem.permissions[itemIndex]) {
            permissionsArray[itemIndex] = new Array();
            permissionsArray[itemIndex][0] = prm.userName;
            permissionsArray[itemIndex][1] = (prm.userAccessType == 0) ? Plugin.messages["FileManager.SharingDialog.view"] : Plugin.messages["FileManager.SharingDialog.fullControl"];
            permissionsArray[itemIndex][2] = prm.notify;
            itemIndex++;
        }
        
        gridDataStore.load();     
    },
    
    save: function() {  
        
        var itemSaved = function(result,success,error) {
            if (!success) {
                Ext.MessageBox.alert(Plugin.messages["FileManager.common.error"], error);
            }
            else {
                this.fireEvent('save', this.folderId, this.getUsersToBeNotified());
                this.close();
            }
        };      
        
        // get values
        shareItem.enabled = chkShareFolder.dom.checked;
        shareItem.comment = txtComment.value;
        
        RemoteMethods.SaveSharedItem(shareItem.folderID, shareItem.enabled, shareItem.comment, shareItem.permissions, itemSaved, this);
    },
    
    addPermission: function(user, permission) {
    
        // don't add empty user
        if(user.trim() == '')
            return;
    
        // see if the user is not added
        var itemIndex = 0;
        var prm = null;
        while (prm = shareItem.permissions[itemIndex]) {
            if(prm.userName.toLowerCase() == user.toLowerCase().trim())
                return;
            itemIndex++;
        }    
    
        var index = shareItem.permissions.length;
        shareItem.permissions[index] = {
            folderID: shareItem.folderID,
            userName: user.trim(),
            userAccessType: permission,
            notify: true
        };
        
        this.bindSharingDialog();
    },
    
    removePermission: function(user) {
    
        var itemIndex = 0;
        var prm = null;
        while (prm = shareItem.permissions[itemIndex]) {
            if(prm.userName.toLowerCase() == user.toLowerCase().trim()) {
                shareItem.permissions.splice(itemIndex, (itemIndex == 0) ? (itemIndex + 1) : itemIndex);                
            }
            itemIndex++;
        }
        
        this.bindSharingDialog();
    },    
    
    toggleSharing: function() {
        var checked = chkShareFolder.dom.checked;
        
        if(checked) {
            sharingForm.enable();
            shareItem.enabled = true;
        }
        else {
            sharingForm.disable();
            shareItem.enabled = false;
        }
    },
    
    getUsersToBeNotified: function() {
        var users = new Array();
        var itemIndex = 0;
        var prm = null;
        while (prm = shareItem.permissions[itemIndex]) {
            if(prm.Notify) {
                users[users.length] = prm.userName;                
            }
            itemIndex++;
        }
        return users;
    },
    
    btnAdd_Click: function() {
        var userInput = Ext.get('x-sharing-dialog-user').dom;
        var prm = 0;
        if (Ext.get('x-sharing-dialog-permission').dom.checked)
            prm = 1;
        var index = 0;
        var ads = userInput.value.split(",");
        var ad = null;
        while(ad = ads[index]) {
            ad = ad.trim();
            if(ad != '') {
                this.addPermission(ad, prm);
            }
            index++;
        }
        userInput.value = '';
    },
    
    btnRemove_Click: function() {
        var rw = permissionsGrid.getSelectionModel().getSelected();
        if (rw)
            this.removePermission(rw.id);
    },
    
    cellDoubleClicked: function(grd, rowIndex, colIndex, e) {        
        
        if(colIndex != 1)
            return;
            
        var dataItem = grd.getStore().data.items[rowIndex].data;
        var user = dataItem.username;
            
        var itemIndex = 0;
        var prm = null;
        while (prm = shareItem.permissions[itemIndex]) {
            if(prm.userName.toLowerCase() == user.toLowerCase().trim()) {
                prm.userAccessType = (prm.userAccessType == 0) ? 1 : 0;
            }
            itemIndex++;
        }
        
        this.bindSharingDialog();        
    },
    
    cellClicked: function(grd, rowIndex, colIndex, e) {        
        
        if(colIndex != 2)
            return;
            
        var dataItem = grd.getStore().data.items[rowIndex].data;
        var user = dataItem.username;
            
        var itemIndex = 0;
        var prm = null;
        while (prm = shareItem.permissions[itemIndex]) {
            if(prm.userName.toLowerCase() == user.toLowerCase().trim()) {
                prm.notify = (prm.notify == true) ? false : true;
            }
            itemIndex++;
        }
        
        this.bindSharingDialog();        
    },    
    
    addNotify: function() {
        var itemIndex = 0;
        var prm = null;
        while (prm = shareItem.permissions[itemIndex]) {
            prm.notify = false;
            itemIndex++;
        }    
    }
        
});


////////////////////////////////////////////////////////////////////
//
//                  FileManager.AddressBook
//
/////////////////////////////////////////////////////////////////// 
FileManager.AddressBook = function(config) {
    
    this.events = {
        "select" : true,
        "cancel" : true        
    };    
    
    this.txtEmail = new Ext.form.TextField({
        fieldLabel: Plugin.messages["FileManager.AddressBook.email"],
        name: 'email',
        width:200,
        allowBlank:false,
        vtype: 'email'
    });
    
    this.txtName = new Ext.form.TextField({
        fieldLabel: Plugin.messages["FileManager.AddressBook.name"],
        name: 'name',
        width:200,
        allowBlank:false
    });
    
    this.addForm = new Ext.form.FormPanel({
        labelWidth:40, 
        labelAlign:'left', 
        buttonAlign:'right',
        frame:true,
        bodyStyle:'padding:5px 5px 0',
        title: Plugin.messages["FileManager.AddressBook.addForm.title"],
        
        items: [this.txtEmail, this.txtName],
        
        buttons: [
            {text:Plugin.messages["FileManager.common.save"], handler:this.addAddress, scope:this},
            {text:Plugin.messages["FileManager.common.cancel"],handler:function(){ this.addContainer.hide(true); }, scope:this}
        ]
    });
    
    // create address list grid
    this.addressListGrid = new Ext.grid.GridPanel({
        title: Plugin.messages["FileManager.AddressBook.addressListGrid.title"],
        autoHeight: true,
        loadMask: true,
        store: new Ext.data.SimpleStore({
            id: 0,
            fields: [{name: 'email'},{name: 'name'}],
            data: []
        }),
        columns: [
            {header: Plugin.messages["FileManager.AddressBook.email"], width: 160, sortable: true, locked: false, dataIndex: "email"},     
            {id: "clName", header: Plugin.messages["FileManager.AddressBook.name"], sortable: true, locked: false, dataIndex: "name"}            
        ],
        viewConfig: {
            forceFit: true
        },
        sm: new Ext.grid.RowSelectionModel({singleSelect:false}),
        autoExpandColumn: 'clName',
                
        tbar: new Ext.Toolbar({items: [
            {
                text: Plugin.messages["FileManager.AddressBook.button.add"], 
                iconCls: 'db-icn-add', 
                handler: function() {
                    if(!this.addContainer) {
                        this.addContainer = this.body.createChild({
                            tag: 'div',
                            style: 'width:270px;top:0'
                        });                            
                        this.addForm.render(this.addContainer);               
                    }         
                    this.addContainer.alignTo(this.addressListGrid.getTopToolbar().getEl(), 'bl');            
                    this.addContainer.show();                
                }, 
                scope: this
            }, '-', {
                text: Plugin.messages["FileManager.AddressBook.button.remove"], 
                iconCls: 'db-icn-delete',
                handler: function() {
                    var rw = this.addressListGrid.getSelectionModel().getSelected();
                    if (rw) {
                        RemoteMethods.RemoveAddress(rw.data.email, this.addressBookLoadComplete, this);                
                    }
                },
                scope: this
            }                        
        ]})
    });    
    
    this.subUserGrid = new Ext.grid.GridPanel({
        title: Plugin.messages["FileManager.AddressBook.subUserGrid.title"],
        autoHeight: true,
        store: new Ext.data.SimpleStore({
            id: 0,
            fields: [{name: 'username'},{name: 'email'},{name: 'name'}],
            data: []
        }),
        columns: [
            {header: Plugin.messages["FileManager.AddressBook.subUserGrid.userName"], width: 100, sortable: true, locked: false, dataIndex: "username"},     
            {header: Plugin.messages["FileManager.AddressBook.email"], width: 130, sortable: true, locked: false, dataIndex: "email"},    
            {id: "clName", header: Plugin.messages["FileManager.AddressBook.name"], sortable: true, locked: false, dataIndex: "name"}          
        ],
        viewConfig: {
            forceFit: true
        },
        sm: new Ext.grid.RowSelectionModel({singleSelect:false}),
        autoExpandColumn: 'clName'
    });       
    
    FileManager.AddressBook.superclass.constructor.call(this, Ext.apply(config, {
        border: true,
        layout: 'fit',
        
        items: new Ext.TabPanel({
            activeTab: 0,
            border: false,
            
            items: [this.addressListGrid,this.subUserGrid],
            
            buttons: [
                {text:Plugin.messages["FileManager.common.select"], handler:this.onSelect, scope:this},
                {text:Plugin.messages["FileManager.common.cancel"], handler:this.onCancel, scope:this}            
            ]            
        })
    }));
    
    // load address book data
    if(this.hideMailAddress) {    	
    } else {
    	RemoteMethods.GetAddressBook(this.addressBookLoadComplete, this);
    }
    
    RemoteMethods.GetSubUsers(this.subUsersLoadComplete, this);
};

Ext.extend(FileManager.AddressBook, Ext.Panel, {

    getTabPanel: function() {
        return this.items.items[0];
    },
    
    addressBookLoadComplete: function(result) {
        this.addressListGrid.store.loadData(result);
    },

    addAddress: function() {
            var email = this.txtEmail.getValue().trim();
            var name = this.txtName.getValue().trim();
            
            if(email == '' || name == '')
                return;
        
            RemoteMethods.AddAddress(email, name, this.addressBookLoadComplete, this);
            
            this.txtEmail.setValue('');
            this.txtName.setValue('');
            
            this.addContainer.hide();
    },
    
    subUsersLoadComplete: function(result) {
        this.subUserGrid.store.loadData(result);
        if (result.length == 0) {
            this.getTabPanel().activate(this.addressListGrid);
            this.subUserGrid.disable();
        }
    },
    
    clearSelections: function() {
        this.addressListGrid.getSelectionModel().clearSelections();
        this.subUserGrid.getSelectionModel().clearSelections();
    },
    
    getSelectedItems: function() {
        var items = new Array();
        
        var ContainsAddress = function(ad) {            
            for (var i = 0; i < items.length; ++i) {
                if (items[i].toLowerCase() == ad.toLowerCase()) {
                    return true;
                }
            }
            return false;
        };
        
        var rw = null;
        var selections = this.addressListGrid.getSelectionModel().getSelections();
        var index = 0;
        var ad = null;
        while(rw = selections[index]) {
            ad = rw.data.email;
            if(!ContainsAddress(ad))
                items[items.length] = ad;
            index++;
        }
        selections = this.subUserGrid.getSelectionModel().getSelections();
        index = 0;
        while(rw = selections[index]) {
            ad = (this.getSubUserName) ? rw.data.username : rw.data.email;
            if(!ContainsAddress(ad))
                items[items.length] = ad;
            index++;
        }     
        
        return items;   
    },
    
    onSelect: function() {
        this.fireEvent('select', this, this.getSelectedItems());
    },
    
    onCancel: function() {
        this.fireEvent('cancel', this);
    }

});

Ext.menu.AddressBookItem = function(config){
    Ext.menu.AddressBookItem.superclass.constructor.call(this, new FileManager.AddressBook(config), config);
    this.addressbook = this.component;
    
    this.addEvents({select: true});
    
    this.addressbook.on("render", function(addressbook){
        addressbook.getEl().swallowEvent("click");
        addressbook.container.addClass("x-menu-date-item");
    });    
    
    this.addressbook.on("select", this.onSelect, this);
    this.addressbook.on("cancel", this.onCancel, this);

};
Ext.extend(Ext.menu.AddressBookItem, Ext.menu.Adapter, {
    onSelect : function(addressbook, selected){
        this.fireEvent("select", this, addressbook, selected);
        Ext.menu.AddressBookItem.superclass.handleClick.call(this);
    },
    
    onCancel : function(addressbook, selected){
        Ext.menu.AddressBookItem.superclass.handleClick.call(this);
    }    
});

Ext.menu.AddressBookMenu = function(config){
    Ext.menu.AddressBookMenu.superclass.constructor.call(this, config);
    this.plain = true;
    var abi = new Ext.menu.AddressBookItem(config);
    this.add(abi);
    this.addressbook = abi.addressbook;
    this.relayEvents(abi, ["select"]);
};
Ext.extend(Ext.menu.AddressBookMenu, Ext.menu.Menu, {
    cls:'x-date-menu'
});


////////////////////////////////////////////////////////////////////
//
//                  Ext.form.AddressBookField
//
/////////////////////////////////////////////////////////////////// 
Ext.form.AddressBookField = Ext.extend(Ext.form.TriggerField,  {

    triggerClass : 'x-form-address-trigger',

    defaultAutoCreate : {tag: "input", type: "text", size: "10", autocomplete: "off"},

    initComponent : function(){
        Ext.form.AddressBookField.superclass.initComponent.call(this);        
    
        this.list = new Ext.Layer({shadow: true, constrain:false });
        this.list.setWidth(400);  
        
        this.elem = this.list.createChild({
            tag: 'div',
            style: 'background-color:#efefec;border:solid 1px #b3b6b0;padding:5px'
        });            
    }, 
    
    validateValue : function(value){
        if(!Ext.form.AddressBookField.superclass.validateValue.call(this, value)){
            return false;
        }
        if(value.length < 1){
             return true;
        }
        
        return true;
    },    
    
    validateBlur : function(){
        return !this.list || !this.list.isVisible();
    },    
    
    getValue : function(){
        return Ext.form.AddressBookField.superclass.getValue.call(this) || "";
    },   
    
    setValue : function(addresses){
        Ext.form.AddressBookField.superclass.setValue.call(this, addresses);
    }, 
    
    onSelect: function() {
        if (this.addressbook) {
            var result = this.getValue();
            var itemIndex = 0;
            var ad = null;
            var ads = this.addressbook.getSelectedItems();
            while(ad = ads[itemIndex]) {
                //ad = ad.trim();
                if (this.getValue().toLowerCase().indexOf(ad.toLowerCase()) == -1) {
                    result += (result == '') ? ad : ', ' + ad;
                }
                itemIndex++;
            }
            this.setValue(result);
            this.list.hide();
        }
    },
    
    onCancel: function() {
        if(this.addressbook) {
            this.list.hide();
        }
    },
      
    onTriggerClick : function(){
        if(this.disabled){
            return;
        }
        if(this.addressbook == null){
            this.addressbook = new FileManager.AddressBook({
                renderTo: this.elem,
                hideMailAddress : this.hideMailAddress,
                getSubUserName: this.getSubUserName || false,
                height: 300,
                width:388
            });
            this.addressbook.on('select', this.onSelect, this);
            this.addressbook.on('cancel', this.onCancel, this);
        }
        this.list.show();
        this.list.alignTo(this.el, "tr-br", [17, 0]);
                
    }

});

////////////////////////////////////////////////////////////////////
//
//                  FileManager.SingleUpload
//
/////////////////////////////////////////////////////////////////// 
FileManager.SingleUpload = function(config) {
    config.closable = false;
    config.resizable = false;
    config.constrain = true;
    config.width = 380;
    config.height = 155; 
    config.renderTo = document.body;  
    config.maximizable = false;
    config.bodyStyle = "padding:5px;";
    config.buttons = [
        {text:Plugin.messages["FileManager.upload.SingleUpload.button.startUpload"], handler:this.startUpload, scope:this},
        {text:Plugin.messages["FileManager.common.cancel"], handler:this.cancelUpload, scope:this},
        {text:Plugin.messages["FileManager.upload.SingleUpload.button.newUpload"], handler:this.newUpload, scope:this},
        {text:Plugin.messages["FileManager.common.close"], handler:this.close, scope:this}
    ]
    
    FileManager.SingleUpload.superclass.constructor.call(this, config);

    // define events for this control
    this.events = {
        "switch" : true,
        "complete" : true
    };        
    
    this.body.addClass('x-dlg-upload');
    helpElm = this.body.createChild({
        tag: 'div',
        cls: 'hlp',
        html: Plugin.messages["FileManager.upload.SingleUpload.tip"]
    });
    
    formElem = this.body.createChild({
        tag: 'form',
        method: 'post',
        action: config.uploadUrl,
        enctype: 'multipart/form-data',
        cls: 'frm'        
    });
    formElem.createChild({
            tag: 'input',
            type: 'hidden',
            name: 'sessionId',
            value: MyDesktop.currentSessionId
    });
    formElem.createChild({
            tag: 'input',
            type: 'hidden',
            name: 'folderId',
            value: config.folderId
    });
    formElem.createChild({
            tag: 'input',
            type: 'hidden',
            name: 'postbackId',
            value: config.postbackId
    });
    formElem.createChild({
            tag: 'input',
            type: 'file',
            name: 'Filedata',
            size: 40
     }).on('change', this.fileInputChange, this);  
            
    updateElem = this.body.createChild({
        tag: 'div',
        cls: 'suc',
        style: 'display:none',
        html: '<div>file number one.jpg</div>'
    });    
    
    swcElem = this.body.createChild({
        tag: 'div',
        cls: 'swc',
        style: 'margin-top: 15px',
        html: Plugin.messages["FileManager.upload.SingleUpload.tip.switch"]
    });     
    Ext.get(swcElem.dom.childNodes[1]).on('click', function() { this.fireEvent('switch', this); }, this);
    
    progressElem = this.body.createChild({
        tag: 'div',
        cls: 'prg',
        style: 'display:none',
        html: '<div class="x-dlg-upload-progress">' + 
                '<div class="x-dlg-upload-progress-bar">&nbsp;</div>' +
              '</div>' +
              '<div class="x-dlg-upload-status">'+Plugin.messages["FileManager.upload.SingleUpload.tip.initilizing"]+'</div>'
    });     
    
    // define progress bar
    prgBar = Ext.get(progressElem.dom.childNodes[0].firstChild);
    prgStat = Ext.get(progressElem.dom.childNodes[1]);
    
    // add buttons to the dialog
    btnUpload = this.buttons[0];
    btnCancel = this.buttons[1];
    btnNew = this.buttons[2];
    btnClose = this.buttons[3];
    
    btnUpload.disable();
    btnCancel.hide();
    btnNew.hide();   
        
};

Ext.extend(FileManager.SingleUpload, Ext.Window, {
    
    isUploading: false,
    
    startUpload: function() {        
        Ext.Ajax.request({
            url : this.uploadUrl,
            params : null,
            method : 'POST',
            form : formElem.dom,
            isUpload : true,
            callback : function(options, success, response) {
                if(success)
                    this.uploadComplete(response.responseText);
                else
                    this.uploadError(response.responseText);   
            },
            success : function(response, options) {
                //Ext.MessageBox.alert('Success', response.responseText);                
            },
            failure : function(response, options) {
                //Ext.MessageBox.alert('Error', response.responseText);  
            },
            scope : this
        });                
        // setup display
        helpElm.update(Plugin.messages["FileManager.upload.SingleUpload.tip.updating"]);
        formElem.applyStyles('position:absolute;left:-1000px');
        swcElem.setDisplayed(false);
        this.resetProgressDisplay();
        progressElem.setDisplayed(true);
        this.isUploading = true;
        btnUpload.hide();
        btnCancel.show();
        btnClose.disable();
        
        this.startProgress.defer(2000, this);  
    },
    cancelUpload: function() {             
        var upload_frame = this.findUploadIframe();
        if (upload_frame) {
        		         
            Ext.lib.Event.purgeElement(upload_frame, true, 'load');
            upload_frame.src = 'about:blank';
            setTimeout(function(){document.body.removeChild(upload_frame);}, 100);
        }
        
        // update the interface
        helpElm.update(Plugin.messages["FileManager.upload.SingleUpload.tip.canceled"]);
        this.setTitle(Plugin.messages["FileManager.upload.SingleUpload.title.canceled"]);
        this.isUploading = false;
        btnClose.enable();
        btnCancel.hide();
        btnNew.show();
    },
    uploadComplete: function(responseText) {
        helpElm.update(Plugin.messages["FileManager.upload.SingleUpload.tip.completed"]);
        this.setTitle(Plugin.messages["FileManager.upload.SingleUpload.title.completed"]);
        this.isUploading = false;
        progressElem.setDisplayed(false);
        updateElem.update(responseText);
        updateElem.setDisplayed(true);  
        swcElem.setDisplayed(true);      
        btnClose.enable();
        btnCancel.hide();
        btnNew.show();
        this.fireEvent('complete', this);
    },
    newUpload: function() {
        helpElm.update(Plugin.messages["FileManager.upload.SingleUpload.tip"]);
        this.setTitle(Plugin.messages["FileManager.upload.SingleUpload.title"]);
        progressElem.setDisplayed(false);
        updateElem.setDisplayed(false);
        swcElem.setDisplayed(true);
        formElem.applyStyles('position:static;');
        formElem.dom.reset();
        btnNew.hide();
        btnUpload.show();
        btnUpload.disable();  
    },
    uploadError: function(responseText) {
        this.isUploading = false;
        Ext.MessageBox.alert(Plugin.messages["FileManager.common.error"], responseText);  
    },
    startProgress: function() {
        this.updateProgress();
    },
    updateProgress: function() {
        RemoteMethods.GetUploadStatus(this.postbackId, this.updateProgressResponse, this);
    },
    updateProgressResponse: function(stat,success,error) {    
        if(stat == null)
        {
            if (this.isUploading) this.updateProgress.defer(1000, this);
            return;
        }
        
        if (!success) {
            this.cancelUpload();
            Ext.MessageBox.alert(Plugin.messages["FileManager.common.error"], error);
            this.setTitle(Plugin.messages["FileManager.common.error"] + ': ' + error);
        } else if (this.isUploading) {
            this.updateProgressDisplay(stat.returnValue, stat.description);
            
            if(stat.returnValue < 100)
                this.updateProgress.defer(2000, this);
        }            
    },
    fileInputChange: function(e, elem) {
        btnUpload.enable();
    },
    findUploadIframe: function() {
        var ifs = Ext.fly(document.body).query('iframe.x-hidden');
        if (ifs.length > 0) {
          return ifs[0];
        }
        return null;
    },
    updateProgressDisplay: function(pr, stat) {
        prgBar.setStyle('width', pr + '%');
        prgStat.update(stat);
        this.setTitle(Plugin.messages["FileManager.upload.SingleUpload.title.uploading"] + " (" + pr + "%)");
    }, 
    resetProgressDisplay: function() {
        this.updateProgressDisplay(0, Plugin.messages["FileManager.upload.SingleUpload.tip.initilizing"]);
    }
});


////////////////////////////////////////////////////////////////////
//
//                  FileManager.TagsPanel
//
/////////////////////////////////////////////////////////////////// 
FileManager.TagsPanel = function(config) {

    // add event
    this.events = {
        "tagselect" : true,
        "tagremove" : true,
        "tagedit" : true
    };    
    
    FileManager.TagsPanel.superclass.constructor.call(this, Ext.applyIf(config||{}, {
        animate:true, 
        containerScroll: true,
        rootVisible:false,
        autoScroll:true,
        title: Plugin.messages["FileManager.TagsPanel.title"]        
    }));        
    
    var root = new Ext.tree.TreeNode({
        text: 'Tags', 
        allowDrag:false,
        allowDrop:false
    });
    this.setRootNode(root);
    
    this.on('contextmenu', this.tagsTree_contextmenu, this);
    this.on('click', this.tagsTree_click, this);
    
    root.expand();  
    
    // create menues
    this.treeMenu = new Ext.menu.Menu();
    this.treeMenu.add(
        {text: 'Open', iconCls: 'db-icn-folder-open', handler: function() { this.selectTag(this.contextTagId); }, scope: this },
        '-', 
        {text: 'Delete', iconCls: 'db-icn-delete', handler: function() { this.deleteTag(this.contextTagId); }, scope: this }
    );      
    
    // load tags
    this.on('render', this.loadTags, this);
}

Ext.extend(FileManager.TagsPanel, Ext.tree.TreePanel, {

    selectTag: function(name) {
        var node = this.getNodeById(name);
        if (node) node.select();
        
        this.fireEvent('tagselect', name);
    },
    
    deleteTag: function(name) {
          
        var TagRemoved = function(result) {
            if(result.CurrentStatus == FileManager.StatusCode.Success) {
                this.fireEvent('tagremove', name);
                this.loadTags();
            } else {
                Ext.MessageBox.alert('Error', result.Description);
            }
        };
        
        RemoteMethods.RemoveTag(name, TagRemoved, this);    
    },    
       
    populateTree: function() {
        
        // get currently selected node
        var selectedNode = this.getSelectionModel().getSelectedNode();
             
        // first we clear the tree nodes
        var node = null;
        while (node = this.root.childNodes[0]) {
            node.unselect();
            this.root.removeChild(node);
        }     
                
        var index = 0
        var tag = null;
        while (tag = this.tags[index]) {
            var title = tag.Name + ' (' + tag.Count + ')';
            this.root.appendChild(
                new Ext.tree.TreeNode({id:tag.Name, text:title, iconCls:'db-icn-tag', allowDrag:false})
            );            
            index++;
        }

        // if we had a selected node before select it again
        if (selectedNode != null)
            this.getSelectionModel().select(this.getNodeById(selectedNode.id));     
    },
       
    
    tagsTree_click: function(node, e) {
        if(node == null || node.id == null)
            return;

        this.selectTag(node.id);
    },
    
    tagsTree_contextmenu: function(node, e) {
        if(node == null || node.id == null)
            return;
            
        this.contextTagId = node.id;
        this.treeMenu.show(node.ui.getAnchor());
    },
    
    loadTags: function() {
        
        var LoadTagsComplete = function(result) {
            this.tags = result;
            this.populateTree();
        };

        RemoteMethods.GetAllTags(LoadTagsComplete, this);
    },
    
    tagItems: function(folderIds, fileIds) {

        var TagsLoaded = function(result) {
            if (result.CurrentStatus == FileManager.StatusCode.Success) {
                tags = result.ReturnValue;
                this.showDialog(folderIds, fileIds, result.ReturnValue);
            } else {
                Ext.MessageBox.alert('Error', result.Description);
            }
        };
        
        RemoteMethods.GetTags(folderIds, fileIds, TagsLoaded, this);       
    },
    
    showDialog: function(folderIds, fileIds, tags) {
    
        var dlg = null;
        var txtTags = null;
        
        var CallServer = function() {
            var sTags = txtTags.getValue();
            
            RemoteMethods.AddTags(folderIds, fileIds, sTags,
                function (result) {
                    dlg.close();
                    if (result.CurrentStatus == FileManager.StatusCode.Success) {
                        if(this.rendered)
                            this.loadTags();
                        this.fireEvent('tagedit', folderIds, fileIds, sTags);
                    } else {
                        Ext.MessageBox.alert('Error', result.Description);
                    }
                }, this); //end of service call
        };    
               
        // create the dialog
        dlg = new Ext.Window({
            title: 'Add Tags to Selected Items',
            iconCls: 'db-icn-tag',
            resizable:false,
            constrainHeader: true,
            modal: true,
            renderTo: (this.ctParent && this.ctParent.cover)? this.ctParent.cover : document.body,
            width: 400,
            height: 300,            
            bodyStyle: 'padding:5px 10px 0 10px',
            html: '<div><span style="padding-bottom:2px;display:block">Tags: <span style="font-size:0.8em">(seperate tags with ,)</span></span><div></div></div><div><span style="padding:10px 0 2px 0;display:block">All Tags:</span><div style="height:150px;overflow:auto;background-color:#fff;border:solid 1px #7F9DB9;"></div></div>',
            
            buttons: [
                {text:'OK',handler:CallServer,scope:this},
                {text:'Cancel', handler:function(){ dlg.close() }}
            ]
        });       

        var formHolderEl = Ext.get(dlg.body.dom.childNodes[0].childNodes[1]);
        var tagsHolderEl = Ext.get(dlg.body.dom.childNodes[1].childNodes[1]);
        
        // Create a textbox that contains this item tags
        txtTags = new Ext.form.TextField({
            width:355,
            value: tags,
            renderTo: formHolderEl
        });     
        
        // Build all tags cloud
        var GetTagStyle = function(t) {
            var size = 0;
            var weight = 100;
            if(t.Count < 9)
                size = t.Count;
            else
                size = 9;
            
            if(t.Count > 9)
                weight = t.Count*10;
            
            weight = (weight > 900)? 900 : weight;
            
            return 'font-size:1.' + size + 'em;font-weight:' + weight + ';padding:0 3px';
        };
        
        var TagClicked = function(e, elem) {
            var sTags = txtTags.getValue();
            var tag = elem.innerHTML;            
            
            var tagList = sTags.split(',');
            for (var i =0; i < tagList.length; ++i) 
                if (tagList[i].trim().toLowerCase() == tag.toLowerCase())
                    return;
            
            if (sTags.trim() == '')
                sTags = tag;
            else
                sTags += ', ' + tag;
            
            txtTags.setValue(sTags);
        };
        
        var LoadTagsComplete = function(result) {
            this.tags = result;
            for(var i =0; i < this.tags.length; ++i) {
                var t = tagsHolderEl.createChild({
                    tag: 'a',
                    href: '#',
                    style: GetTagStyle(this.tags[i]),
                    html: this.tags[i].Name
                });
                
                t.on('click', TagClicked, this);
            }
        };        
        
        // make sure tags are loaded
        if(!this.tags) {
            RemoteMethods.GetAllTags(LoadTagsComplete, this);
        } else  {
            LoadTagsComplete(this.tags);
        }      

        dlg.show();
    }
});


////////////////////////////////////////////////////////////////////
//
//                  FileManager.MediaPlayer
//
/////////////////////////////////////////////////////////////////// 
FileManager.MediaPlayer = function(config) {   

    var player = "";
    var playerWidth = 400;
    var playerHeight = 300;
    var isIE = window.ActiveXObject ? true : false;
       
    if (config.fileName.match(/\.mp3$/i)) {
        playerHeight = 24;
        playerWidth = 295;
        
        config.collapsible = true;
        config.modal = false;
        config.resizable = false;
        
        player += '<object type="application/x-shockwave-flash" data="../file/player.swf" id="mp3Player" height="24" width="290" style="margin:7px 0 0 5px">'
        player += '<param name="movie" value="../file/player.swf">';
        player += '<param name="quality" value="high">';
        player += '<param name="menu" value="false">';
        player += '<param name="wmode" value="transparent">';
        player += '<param name="FlashVars" value="loop=yes&amp;autostart=yes&amp;soundFile=' + config.url + '">'
        player += '</object>';                    
    
    } else if (config.fileName.match(/\.mov$|\.mp4$|\.m4v$|\.m4b$|\.3gp$|\.m4a$/i)) {
        this.quicktime = true;
        if (config.fileName.match(/\.m4a$/))
            playerHeight = 16;
        else
            playerHeight = 316;
            
        if(isIE) {
            player = '<object id="player" classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" codebase="http://www.apple.com/qtactivex/qtplugin.cab" width="100%" height="100%">' +
                '<param name="src" value="'+config.url+'" />' +
                '<param name="controller" value="true" />' +
                '<param name="autoplay" value="false" />' +
                '<param name="kioskmode" value="true" />' +
                '<param name="loop" value="true" />' +
                '<param name="scale" value="tofit" />' +
                '</object>'
        } else {
            player = '<object id="player" type="video/quicktime" data="'+config.url+'" width="100%" height="100%">' +
                '<param name="autoplay" value="false" />' +
                '<param name="controller" value="true" />' +
                '<param name="kioskmode" value="true" />' +
                '<param name="loop" value="true" />' +
                '<param name="scale" value="tofit" />' +                
                '</object>'
        }
        
    } else if (config.fileName.match(/\.asf$|\.avi$|\.wmv$|\.mpg$|\.wma$/i)) {
        this.quicktime = false;
        if (config.fileName.match(/\.wma$|\.mp3$/))
            playerHeight = 64;
        else
            playerHeight = 372;
        
        if (isIE) {
            player = '<object classid="CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6" id="player" width="100%" height="100%">' +
                '<param name="url" value="'+config.url+'" />' +
                '<param name="showcontrols" value="true" />' +
                '<param name="showstatusbar" value="true" /> ' +
                '<param name="autostart" value="true" />' +
                '<param name="stretchtofit" value="true" /> ' +
                '</object>';            
        } else {
            player = '<object type="video/x-ms-wmv" data="'+config.url+'" width="100%" height="100%" id="player">' +
                '<param name="src" value="'+config.url+'" />' +
                '<param name="autostart" value="true" />' + 
                '<param name="showstatusbar" value="true" /> ' +
                '<param name="controller" value="true" />' +
                '<param name="stretchtofit" value="true" /> ' +
                '</object>';                
        }                
    }

    config.title = config.fileName || "Media Player";      
    config.html = player;
    config.width = playerWidth + 20;
    config.height = playerHeight + 45;
    config.constrainHeader = true;
     
    FileManager.MediaPlayer.superclass.constructor.call(this, config);
    
    this.on('beforeclose', this.player_beforeclose, this); 
};

Ext.extend(FileManager.MediaPlayer, Ext.Window, {       
    player_beforeclose: function() {
        var player = this.body.dom.firstChild;
        
        if(!player) return;
        
        // stop the player
        try {
            if(this.quicktime && player.Stop)
                player.Stop();
            else if(player.controls)
                player.controls.stop();
        } catch(err) {
            // do nothing!
        }
            
        player.style.visibility = "hidden";
        this.body.dom.removeChild(player);
        player = null;
        playerpElm = null;
        this.getEl().remove();
    }
    
});


////////////////////////////////////////////////////////////////////
//
//                  FileManager.PublishedFolder
//
/////////////////////////////////////////////////////////////////// 
FileManager.PublishedFolder = function(config) {

    this.events = {
        "publish" : true,
        "unpublish" : true,
        "error": true,
        "email": true           
    };
    
    FileManager.PublishedFolder.superclass.constructor.call(this, Ext.applyIf(config || {}, {
        title: Plugin.messages["FileManager.PublishedFolder.title.default"],
        width: 380,     
        autoHeight:true,           
        border: true,

        
        items: new Ext.FormPanel({
            bodyStyle:'background-color:transparent',
            defaultType: 'textfield',    
            border: false,
            autoHeight:true,
            labelWidth: 60,
            
            items: [{
                xtype: 'fieldset',
                title: Plugin.messages["FileManager.PublishedFolder.fieldset.link.title"],
                autoHeight: true,
                defaultType: 'textfield',
                defaults: {width: 330}, 
                labelAlign: 'top',
                
                items: [{
                        fieldLabel: '&nbsp;&nbsp;'+Plugin.messages["FileManager.PublishedFolder.directUrl"]+' <span style="font-size:0.9em">(<a id="db-pf-url-link" href="#" target="_blank">'+Plugin.messages["FileManager.PublishedFolder.gotoUrl"]+'</a>)</span>',
                        id: 'db-pf-url',
                        selectOnFocus: true,
                        readOnly: true
                    },{
                        fieldLabel: '&nbsp;&nbsp;<img src="../file/images/icons/rss.gif" style="margin-bottom:-3px" /> '+Plugin.messages["FileManager.PublishedFolder.rssUrl"]+' <span style="font-size:0.9em">(<a id="db-pf-rss-link" href="#" target="_blank">'+Plugin.messages["FileManager.PublishedFolder.gotoRss"]+'</a>)</span>',
                        id: 'db-pf-rss',
                        selectOnFocus: true,
                        readOnly: true 
                    }
                ]    
            },{
                xtype:'fieldset',
                id: 'db-pf-expire',
                checkboxToggle:true,
                title: Plugin.messages["FileManager.PublishedFolder.fieldset.expire.title"],
                autoHeight:true,
                defaults: {width: 210},
                defaultType: 'textfield',
                collapsed: true,
                
                items :[new Ext.form.DateField({
                        fieldLabel: Plugin.messages["FileManager.PublishedFolder.fieldset.expire.date"],
                        format: 'Y-m-d',
                        id: 'db-pf-date',                        
                        readOnly: true
                    }), new Ext.form.TimeField({
                        fieldLabel: Plugin.messages["FileManager.PublishedFolder.fieldset.expire.time"],
                        name: 'time',
                        id: 'db-pf-time',
                        maxHeight: 150,
                        readOnly: true
                    })
                ]
            },{
                xtype:'fieldset',
                id: 'db-pf-protect',
                checkboxToggle:true,
                title: Plugin.messages["FileManager.PublishedFolder.fieldset.protect.title"],
                autoHeight:true,
                defaults: {width: 170},
                defaultType: 'textfield',
                collapsed: true,
                labelWidth: 100,
                
                items :[{
                        fieldLabel: Plugin.messages["FileManager.PublishedFolder.fieldset.protect.password"],
                        id: 'db-pf-pass1',
                        inputType: 'password'
                    }, {
                        fieldLabel: Plugin.messages["FileManager.PublishedFolder.fieldset.protect.confirm"],
                        id: 'db-pf-pass2',
                        inputType: 'password'
                    }
                ]
            },{
                xtype:'fieldset',
                id: 'db-pf-cmt',
                checkboxToggle:true,
                title: Plugin.messages["FileManager.PublishedFolder.fieldset.comment.title"],
                autoHeight:true,
                defaultType: 'textarea',
                collapsed: true,
                hideLabels: true,
                
                items :[{
                        name: 'comment',
                        id: 'db-pf-comment',
                        inputType: 'password',
                        width: 330,
                        height: 70
                    }
                ]
            }]             
        }),
        
        buttons: [
            {text: Plugin.messages["FileManager.PublishedFolder.removePublishing"], handler: this.unpublish, scope: this},
            {text: Plugin.messages["FileManager.PublishedFolder.emailLinks"], handler: this.email, scope: this},
            {text: Plugin.messages["FileManager.common.ok"], handler: this.update, scope: this}
        ]     
    }));   
    
};

Ext.extend(FileManager.PublishedFolder, Ext.Window, {
    
    // private
    onRender : function(ct, position){
        FileManager.PublishedFolder.superclass.onRender.call(this, ct, position);
        
        this.txtUrl = Ext.ComponentMgr.get('db-pf-url');
        this.txtRss = Ext.ComponentMgr.get('db-pf-rss');
        this.txtDate = Ext.ComponentMgr.get('db-pf-date');
        this.txtTime = Ext.ComponentMgr.get('db-pf-time');
        this.txtPass1 = Ext.ComponentMgr.get('db-pf-pass1');
        this.txtPass2 = Ext.ComponentMgr.get('db-pf-pass2');
        this.txtComment = Ext.ComponentMgr.get('db-pf-comment');
        
        this.fsExpire = Ext.ComponentMgr.get('db-pf-expire');
        this.fsProtect = Ext.ComponentMgr.get('db-pf-protect');
        this.fsComment = Ext.ComponentMgr.get('db-pf-cmt');
        
        // I couldn't find a better way to sync body size!
        this.fsExpire.on('expand', this.syncSize, this);
        this.fsExpire.on('collapse', this.syncSize, this);        
        this.fsProtect.on('expand', this.syncSize, this);
        this.fsProtect.on('collapse', this.syncSize, this);        
        this.fsComment.on('expand', this.syncSize, this);
        this.fsComment.on('collapse', this.syncSize, this);                
    },
    
    publish : function() {
        RemoteMethods.PublishFolder(this.folderId, false, new Date(), false, null, false, null, false, 
        	function(result,success,error) {
	            if (success) {
	                var pfi = result.ReturnValue; 
	                var pd = Date.parseDate(pfi.expireDate, 'Y/m/d H:i');
	                this.txtUrl.setValue(pfi.directUrl);
	                this.txtRss.setValue(pfi.rssUrl);
	                if (pfi.enableExpiration === true) this.fsExpire.expand();
	                this.txtDate.setValue(pd);
	                this.txtTime.setValue(pd);
	                if(pfi.enablePassword === true) this.fsProtect.expand();
	                this.txtPass1.setValue(pfi.password);
	                this.txtPass2.setValue(pfi.password);
	                if(pfi.enableComment === true) this.fsComment.expand();
	                this.txtComment.setValue(pfi.comment);
	                Ext.getDom('db-pf-url-link').href = pfi.directUrl;
	                Ext.getDom('db-pf-rss-link').href = pfi.rssUrl;                
	                this.fireEvent("publish", this, pfi);
	                this.show();
	            } else {
	                this.fireEvent("error", this, error);            
	            }
	        }, this
	    ); 
    },
    
    update : function() {
        var expireDate = new Date();
        try {
            expireDate = this.txtDate.getValue().format('Y-m-d') + ' ' + Date.parseDate(this.txtTime.getValue(), this.txtTime.format).format('H:i:s');
        } catch (err) {
            // do nothing
        }
        
        // check if password and conform password are the same
        if(this.txtPass1.getValue() != this.txtPass2.getValue()) {
            this.fireEvent("error", this, Plugin.messages["FileManager.PublishedFolder.fieldset.protect.error.notSame"]); 
            return;
        }
        
        RemoteMethods.PublishFolder(this.folderId, !this.fsExpire.collapsed, expireDate, !this.fsProtect.collapsed, this.txtPass1.getValue(), !this.fsComment.collapsed, this.txtComment.getValue(), true, function(result,success,error) {
            if (success) {
            	this.fireEvent("publish", this);
                this.close();
            } else {
                this.fireEvent("error", this, error);            
            }                      
        }, this);        
    },
    
    unpublish: function() {
        this.fireEvent("unpublish", this);
        this.close();
    },
    
    email : function() {
        this.fireEvent("email", this);
    }
    
});


////////////////////////////////////////////////////////////////////
//
//                  FileManager.PublishedFile
//
/////////////////////////////////////////////////////////////////// 
FileManager.PublishedFile = function(config) {

    this.events = {
        "publish" : true,
        "unpublish" : true,
        "error": true,
        "email": true           
    };
    
    FileManager.PublishedFile.superclass.constructor.call(this, Ext.applyIf(config || {}, {
        title: Plugin.messages["FileManager.PublishedFile.title.default"],
        width: 380,     
        autoHeight:true,           
        border: true,

        
        items: new Ext.FormPanel({
            bodyStyle:'background-color:transparent',
            defaultType: 'textfield',    
            border: false,
            autoHeight:true,
            labelWidth: 60,
            
            items: [{
                xtype: 'fieldset',
                title: Plugin.messages["FileManager.PublishedFile.fieldset.link.title"],
                autoHeight: true,
                defaultType: 'textfield',
                defaults: {width: 330}, 
                labelAlign: 'top',
                
                items: [{
                        fieldLabel: '&nbsp;'+Plugin.messages["FileManager.PublishedFile.directUrl"]+' <span style="font-size:0.9em">(<a id="db-pf-url-link" href="#" target="_blank">'+Plugin.messages["FileManager.PublishedFile.gotoUrl"]+'</a>)</span>',
                        id: 'db-pf-url',
                        selectOnFocus: true,
                        readOnly: true
                    },{
                        fieldLabel: '&nbsp;'+Plugin.messages["FileManager.PublishedFile.downloadUrl"]+' <span style="font-size:0.9em">(<a id="db-pf-down-link" href="#">'+Plugin.messages["FileManager.PublishedFile.gotoUrl"]+'</a>)</span>',
                        id: 'db-pf-down',
                        selectOnFocus: true,
                        readOnly: true 
                    }
                ]    
            },{
                xtype:'fieldset',
                id: 'db-pf-expire',
                checkboxToggle:true,
                title: Plugin.messages["FileManager.PublishedFile.fieldset.expire.title"],
                autoHeight:true,
                defaults: {width: 210},
                defaultType: 'textfield',
                collapsed: true,
                
                items :[new Ext.form.DateField({
                        fieldLabel: Plugin.messages["FileManager.PublishedFile.expireDate"],
                        format: 'Y-m-d',
                        id: 'db-pf-date',                        
                        readOnly: true
                    }), new Ext.form.TimeField({
                        fieldLabel: Plugin.messages["FileManager.PublishedFile.expireTime"],
                        name: 'time',
                        id: 'db-pf-time',
                        readOnly: true
                    })
                ]
            }]             
        }),
        
        buttons: [
            {text: Plugin.messages["FileManager.PublishedFile.removePublishing"], handler: this.unpublish, scope: this},
            {text: Plugin.messages["FileManager.PublishedFile.emailLinks"], handler: this.email, scope: this},
            {text: Plugin.messages["FileManager.common.ok"], handler: this.update, scope: this}
        ]     
    }));   
    
};

Ext.extend(FileManager.PublishedFile, Ext.Window, {
    
    // private
    onRender : function(ct, position){
        FileManager.PublishedFile.superclass.onRender.call(this, ct, position);
        
        this.txtUrl = Ext.ComponentMgr.get('db-pf-url');
        this.txtDown = Ext.ComponentMgr.get('db-pf-down');
        this.txtDate = Ext.ComponentMgr.get('db-pf-date');
        this.txtTime = Ext.ComponentMgr.get('db-pf-time');                
        this.fsExpire = Ext.ComponentMgr.get('db-pf-expire');
        
        // I couldn't find a better way to sync body size!
        this.fsExpire.on('expand', this.syncSize, this);
        this.fsExpire.on('collapse', this.syncSize, this);                      
    },
    
    publish : function() {
        RemoteMethods.PublishFile(this.fileId, false, new Date(), false, function(result,success,error) {
        	if(success) { 
                var pfi = result.ReturnValue; 
                var pd = Date.parseDate(pfi.expireDate, 'Y/m/d H:i');
                this.txtUrl.setValue(pfi.directUrl);
                this.txtDown.setValue(pfi.downloadUrl);
                if (pfi.enableExpiration === true) this.fsExpire.expand();
                this.txtDate.setValue(pd);
                this.txtTime.setValue(pd);
                Ext.getDom('db-pf-url-link').href = pfi.directUrl;
                Ext.getDom('db-pf-down-link').href = pfi.downloadUrl;
                this.fireEvent("publish", this, pfi);
                this.show();
            } else {
                this.fireEvent("error", this, error);            
            }
        }, this); 
    },
    
    update : function() {
        var expireDate = new Date();
        try {
            expireDate = this.txtDate.getValue().format('Y-m-d') + ' ' + Date.parseDate(this.txtTime.getValue(), this.txtTime.format).format('H:i:s');
        } catch (err) {
            // do nothing
        }
        
        RemoteMethods.PublishFile(this.fileId, !this.fsExpire.collapsed, expireDate, true, function(result,success,error) {
            if (success) {
            	this.fireEvent("publish", this);
                this.close();
            } else {
                this.fireEvent("error", this, error);            
            }                      
        }, this);        
    },
    
    unpublish: function() {
        this.fireEvent("unpublish", this);
        this.close();
    },
    
    email : function() {
        this.fireEvent("email", this);
    }
    
});


////////////////////////////////////////////////////////////////////
//
//                  FileManager.UploadFromUrl
//
/////////////////////////////////////////////////////////////////// 
FileManager.UploadFromUrl = function(config) {

    this.events = {
        "upload" : true      
    };
    
    this.urlRegExp = /(http|https|ftp):\/\/(\w+:{0,1}\w*@)?([^:\/\s]+(:[0-9]+)?)((\/\w+)*\/)?([\w\-\.]+\.[^#?\s]+)?(#[\w\-]+)?/;
    
    FileManager.UploadFromUrl.superclass.constructor.call(this, Ext.applyIf(config || {}, {
        title: 'Upload From Url',
        cls: 'db-ufu-win',
        width: 380,   
        height: 195,         
        border: true,
        layout: 'card',
        activeItem: 0,
        
        items: [new Ext.FormPanel({
            defaultType: 'textfield',    
            border: false,
            labelAlign: 'top',
            title: 'Please provide a http or ftp URL to download the file.',
            bodyStyle: 'background-color:transparent;padding:5px 0 0 10px',
            iconCls: 'db-icn-info',
            
            items: [{
                    fieldLabel: '&nbsp;URL <span style="font-size:0.8em;color:#666">(for example: http://www.mydomain.com/myfile.txt)</span>',
                    id: 'db-ufu-url',
                    width: 350,
                    allowBlank: false,
                    regex : this.urlRegExp,
                    regexText: 'This is not a valid url.'
                },{
                    fieldLabel: '&nbsp;File Name',
                    id: 'db-ufu-name',
                    width: 150,
                    allowBlank: false
                }
            ]             
        }), {
            layout: 'fit',
            border: false,
            bodyStyle: 'background-color:transparent'
        }, {
            layout: 'fit',
            border: false,
            bodyStyle: 'background-color:transparent'
        }, {
            layout: 'fit',
            border: false,
            bodyStyle: 'background-color:transparent'
        }],
        
        buttons: [
            {text: 'Close', handler: this.close, scope: this},
            {text: 'Upload', handler: this.upload, scope: this},
            {text: 'New Upload', handler: this.newUpload, hidden: true, scope: this}
        ]     
    }));   
    
};

Ext.extend(FileManager.UploadFromUrl, Ext.Window, {
    
    // private
    onRender : function(ct, position){
        FileManager.UploadFromUrl.superclass.onRender.call(this, ct, position);
        
        this.txtUrl = Ext.ComponentMgr.get('db-ufu-url');
        this.txtName = Ext.ComponentMgr.get('db-ufu-name');
        
        this.on('beforeclose', this.onBeforeClose, this);
        this.txtUrl.on('change', this.onUrlChange, this);
    },
    
    upload : function() {    
        if (!this.txtUrl.isValid() || !this.txtName.isValid()) {
            return;
        }
        
        // show progress
        this.showProgress();        
        this.currentUpload = {url:this.txtUrl.getValue(),folderId:this.folderId,fileName:this.txtName.getValue()};
        RemoteMethods.UploadFromUrl(this.txtUrl.getValue(), this.folderId, this.txtName.getValue(), function(result) {
            if (result.CurrentStatus == FileManager.StatusCode.Success) {
                this.fireEvent("upload", this, this.folderId);
                this.showSuccess(result.Description);
                
            } else {
                this.showError(result.Description);
                     
            }
            this.currentUpload = null;
        }, this); 
    },
    
    showProgress : function() {
        this.getLayout().setActiveItem(1);
        this.buttons[1].hide();
        this.getLayout().activeItem.body.update(
            '<div class="prg">' + 
                '<p class="hlp">The file is being uploaded to your account.</p>' +
                '<p class="bar"><span>Uploading...</span></p>' +
                '<p class="center">Please Wait...</p>' +
            '</div>');
    },
    
    showError : function(msg) {
        this.getLayout().setActiveItem(2);
        this.buttons[2].show();
        this.getLayout().activeItem.body.update(
            '<div class="err">' +
                '<p class="hlp">There was a problem with uploading "' + this.currentUpload.fileName +  '":</p>' + 
                '<p class="info">' + msg + '</p>' +
            '</div>');
    },
    
    showSuccess : function(msg) {
        this.getLayout().setActiveItem(2);
        this.buttons[2].show();
        this.getLayout().activeItem.body.update(
            '<div class="suc">' +
                '<p class="hlp">Your file uploaded to server successfully:</p>' + 
                '<p class="info">' + msg + '</p>' +
            '</div>');            
    },
    
    newUpload : function(msg) {
        this.getLayout().setActiveItem(0);
        this.buttons[1].show();
        this.buttons[2].hide();
        this.txtUrl.setValue('');
        this.txtName.setValue('');
    },
    
    onUrlChange : function() {
        var pu = this.parseUrl(this.txtUrl.getValue());
        if (pu && pu.file) {
            this.txtName.setValue(pu.file);
        }
    },
    
    parseUrl : function(url) {
        if (url.match(this.urlRegExp)) {
            return  {url: RegExp['$&'],
                    protocol: RegExp.$1,
                    authority: RegExp.$2,
                    host:RegExp.$3,
                    path:RegExp.$5,
                    file:RegExp.$7,
                    hash:RegExp.$8};
        }
        else {
            return null;
        }
    },    
    
    onBeforeClose: function(wnd) {
        if (!this.currentUpload)
            return true;
            
        Ext.Msg.show({
            title:"Close upload dialog?",
            msg: "There is still an active upload. Are you sure you want to close these window?",
            buttons: Ext.Msg.YESNO,           
            icon: Ext.MessageBox.QUESTION,
            modal: false,
            scope: this,
            fn: function(btn) {
                if(btn == 'yes') {
                    this.currentUpload = null;
                    this.close();
                }
            }
        });

        return false;
    }    
    
});


////////////////////////////////////////////////////////////////////
//
//                  FileManager.BrowserHistory
//
/////////////////////////////////////////////////////////////////// 
FileManager.BrowserHistory = function() {
    this._position = -1;
    this._length = 0;
    this._addNewEntry = true;
    this._history = new Array();
};

FileManager.BrowserHistory.prototype = {

    getPosition: function() {
        return this._position;
    },
    
    setPosition: function(val) {
        this._position = val;
    },
    
    getCurrentEntry: function() {
        return this._history[this._position];  
    },

    addEntry: function(folderId) {
        if (this._addNewEntry && this.getCurrentEntry() != folderId) {
            this._position += 1;
            this._history[this._position] = folderId;
            this._length = this._position + 1;
        } else {
            this._addNewEntry = true;
        }
    },
    
    canGoBack: function() {
        if (this._position > 0)
            return true;
        else
            return false;
    },
    
    goBack: function() {
        if (this.canGoBack()) {
            this._position -= 1;
            this._addNewEntry = false;
            return true;
        }
        return false;
    },   
    
    canGoForward: function() {
        if (this._position < this._length - 1)
            return true;
        else
            return false;
    },
    
    goForward: function() {
        if (this.canGoForward()) {
            this._position += 1;
            this._addNewEntry = false;
            return true;
        }
        return false;
    }
};


////////////////////////////////////////////////////////////////////
//
//                  Utility functions
//
/////////////////////////////////////////////////////////////////// 
var Utility = function() {

    return {
        formatSize: function(size) {
            if (size == 0) {
                return "";
            }
	        if (size<1024) {
		        return Math.floor(size*100)/100+" bytes";
	        }
	        if (size<1048576) {
		        return Math.floor((size/1024)*100)/100+" KB";
	        }
	        if (size<1073741824) {
		        return Math.floor((size/1048576)*100)/100+" MB";
	        }
	        return Math.floor((size/1073741824)*100)/100+" GB";      
        },        

        isImage: function(name) {
            var regExp = /\.jpg$|\.jpeg$|\.gif$|\.png$|\.bmp$/i;
            if(regExp.test(name))
                return true;
            else
                return false;
        }
        
    };
}();


String.prototype.ellipse = function(maxLength){
    if(this.length > maxLength){
        return this.substr(0, maxLength-3) + '...';
    }
    return this;
};

String.prototype.trim = function() {
    return this.replace(/^\s+|\s+$/g, '');
};

String.prototype.normalize = function() { 
    return this.trim().replace(/\s+/g,' '); 
};

String.prototype.startsWith = function(str,i){ 
    i=(i)?'i':'';
    var re=new RegExp('^'+str,i);
    return (this.normalize().match(re)) ? true : false ;
};

String.prototype.endsWith = function(str,i){ 
    i=(i)?'gi':'g';
    var re=new RegExp(str+'$',i);
    return (this.normalize().match(re)) ? true : false ; 
};